package com.example.composableexample.pager.indecator

import android.util.Log
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Surface
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.lerp
import coil.compose.AsyncImage
import com.example.composableexample.autoscroll.autoScroll
import com.example.composableexample.ui.theme.ComposableExampleTheme
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.HorizontalPagerIndicator
import com.google.accompanist.pager.PagerState
import com.google.accompanist.pager.calculateCurrentOffsetForPage
import com.google.accompanist.pager.rememberPagerState
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.math.abs
import kotlin.math.absoluteValue

data class Page(val url: String)

@Preview
@Composable
fun PagePreview() {
    ComposableExampleTheme {
        Surface(
            modifier = Modifier
                .fillMaxSize()
                .background(MaterialTheme.colorScheme.background)
        ) {
            Pager()
        }
    }
}


val pagers = listOf(
    Page(url = "https://cdn.pixabay.com/photo/2022/10/16/13/53/early-morning-7525151_960_720.jpg"),
    Page(url = "https://cdn.pixabay.com/photo/2016/03/04/19/36/beach-1236581_960_720.jpg"),
    Page(url = "https://cdn.pixabay.com/photo/2013/07/18/20/26/sea-164989_960_720.jpg"),
    Page(url = "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885_960_720.jpg"),
    Page(url = "https://cdn.pixabay.com/photo/2014/04/14/20/11/pink-324175_960_720.jpg"),
    Page(url = "https://cdn.pixabay.com/photo/2016/02/17/19/08/lotus-1205631_960_720.jpg"),
    Page(url = "https://cdn.pixabay.com/photo/2015/04/19/08/33/flower-729512_960_720.jpg"),
    Page(url = "https://cdn.pixabay.com/photo/2015/04/19/08/32/rose-729509_960_720.jpg"),
    Page(url = "https://cdn.pixabay.com/photo/2015/03/30/20/33/heart-700141_960_720.jpg"),
    Page(url = "https://cdn.pixabay.com/photo/2015/05/11/14/51/heart-762564_960_720.jpg")
)

@OptIn(ExperimentalPagerApi::class)
@Composable
fun Pager() {
    val pagerState = rememberPagerState()

    LaunchedEffect(key1 = pagerState.currentPageOffset) {
        while (true) {
            delay(3000)
            val position = (pagerState.currentPage + 1) % pagers.size
            pagerState.animateScrollToPage(position)
        }
    }


    Box(modifier = Modifier.fillMaxSize()) {
        HorizontalPager(
            count = pagers.size, state = pagerState,
            modifier = Modifier
                .fillMaxSize()
                .background(Color.LightGray),
            contentPadding = PaddingValues(horizontal = 50.dp),
        ) { page ->
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .graphicsLayer {
                        // Calculate the absolute offset for the current page from the
                        // scroll position. We use the absolute value which allows us to mirror
                        // any effects for both directions
                        val pageOffset = calculateCurrentOffsetForPage(page).absoluteValue

                        // We animate the scaleX + scaleY, between 85% and 100%
                        lerp(
                            start = 0.85f.toDp(),
                            stop = 1f.toDp(),
                            fraction = 1f - pageOffset.coerceIn(0f, 1f)
                        ).also { scale ->
                            scaleX = scale.toPx()
                            scaleY = scale.toPx()
                        }

                        // We animate the alpha, between 50% and 100%
                        alpha = lerp(
                            start = 0.5f.toDp(),
                            stop = 1f.toDp(),
                            fraction = 1f - pageOffset.coerceIn(0f, 1f)
                        ).toPx()
                    }
                    .fillMaxWidth()
                    .aspectRatio(1f)
            ) {
                Surface(modifier = Modifier.fillMaxWidth()) {
                    AsyncImage(
                        model = pagers[page].url,
                        contentDescription = "image",
                        contentScale = ContentScale.FillHeight
                    )
                }
            }
        }
        Box(
            modifier = Modifier
                .align(Alignment.BottomCenter)
                .padding(bottom = 16.dp)
        ) {
            Column(horizontalAlignment = Alignment.CenterHorizontally) {
                HorizontalPagerIndicator(
                    pagerState = pagerState,
                    activeColor = Color.Blue,
                    inactiveColor = Color.Gray
                )
                Spacer(modifier = Modifier.height(8.dp))
                HorizontalPagerIndicator(
                    pagerState = pagerState,
                    activeColor = Color.Red,
                    inactiveColor = Color.White,
                    indicatorShape = RoundedCornerShape(size = 2.dp)
                )
                Spacer(modifier = Modifier.height(8.dp))
                HorizontalPagerIndicator(
                    pagerState = pagerState,
                    activeColor = Color.Yellow,
                    inactiveColor = Color.DarkGray,
                    indicatorShape = RectangleShape
                )
                Spacer(modifier = Modifier.height(8.dp))
                HorizontalPagerIndicator(
                    pagerState = pagerState,
                    activeColor = Color.Black,
                    inactiveColor = Color(0xff00bb00),
                    indicatorShape = CutCornerShape(4.dp)
                )
                Spacer(modifier = Modifier.height(8.dp))
                CustomPagerIndicatorFirstTry(
                    pagerState = pagerState
                )
                Spacer(modifier = Modifier.height(8.dp))
                CustomPagerIndicatorSecondTry(
                    pagerState = pagerState,
                    indicatorColor = Color.Cyan
                )
                Spacer(modifier = Modifier.height(8.dp))
                CustomPageIndicatorSolution(
                    pagerState = pagerState,
                    indicatorColor = Color.Magenta
                )
            }
        }
    }
}

private const val MULTIPLIER_SELECTED_PAGE = 4
private val baseWith = 4.dp
private val spacing = 10.dp
private val height = 8.dp

@OptIn(ExperimentalPagerApi::class)
@Composable
fun CustomPagerIndicatorFirstTry(
    pagerState: PagerState,
    modifier: Modifier = Modifier,
    indicatorColor: Color = Color.Black
) {
    Row {
        val currentPageWith =
            baseWith * (1 + (1 - abs(pagerState.currentPageOffset)) * MULTIPLIER_SELECTED_PAGE)
        val targetPageWith =
            baseWith * (1 + abs(pagerState.currentPageOffset) * MULTIPLIER_SELECTED_PAGE)
        Log.d(
            "Indicator First Try",
            "currentPage: ${pagerState.currentPage}" +
                    " targetPage: ${pagerState.targetPage}" +
                    "  offset: ${pagerState.currentPageOffset}" +
                    " currentPageWith: $currentPageWith targetPageWith: $targetPageWith"
        )
        repeat(pagerState.pageCount) { index ->
            val with = when (index) {
                pagerState.currentPage -> currentPageWith
                pagerState.targetPage -> targetPageWith
                else -> baseWith
            }
            Box(
                modifier = Modifier
                    .width(with)
                    .background(indicatorColor)
                    .height(height)
            )
            if (index != pagerState.pageCount - 1) {
                Spacer(modifier = Modifier.width(spacing))
            }
        }
    }
}

@OptIn(ExperimentalPagerApi::class)
@Composable
fun CustomPagerIndicatorSecondTry(
    pagerState: PagerState,
    modifier: Modifier = Modifier,
    indicatorColor: Color = Color.Black
) {
    Row {
        val currentPage = pagerState.currentPage
        val targetPage = if (pagerState.currentPageOffset < 0) currentPage - 1 else currentPage + 1
        val currentPageWith =
            baseWith * (1 + (1 - abs(pagerState.currentPageOffset)) * MULTIPLIER_SELECTED_PAGE)
        val targetPageWith =
            baseWith * (1 + abs(pagerState.currentPageOffset) * MULTIPLIER_SELECTED_PAGE)
        Log.d(
            "Indicator Second Try",
            "currentPage: $currentPage" +
                    " targetPage: $targetPage" +
                    "  offset: ${pagerState.currentPageOffset}" +
                    " currentPageWith: $currentPageWith targetPageWith: $targetPageWith"
        )
        repeat(pagerState.pageCount) { index ->
            val with = when (index) {
                currentPage -> currentPageWith
                targetPage -> targetPageWith
                else -> baseWith
            }
            Box(
                modifier = Modifier
                    .width(with)
                    .background(indicatorColor)
                    .height(height = height)
            )
            if (index != pagerState.pageCount - 1) {
                Spacer(modifier = Modifier.width(spacing))
            }
        }
    }
}

@OptIn(ExperimentalPagerApi::class)
@Composable
fun CustomPageIndicatorSolution(
    pagerState: PagerState,
    modifier: Modifier = Modifier,
    indicatorColor: Color = Color.Black
) {
    Row {
        val offsetIntPart = pagerState.currentPageOffset.toInt()
        val offsetFractionalPart = pagerState.currentPageOffset - offsetIntPart
        val currentPage = pagerState.currentPage + offsetIntPart
        val targetPage = if (pagerState.currentPageOffset < 0) currentPage - 1 else currentPage + 1
        val currentPageWith =
            baseWith * (1 + (1 - abs(offsetFractionalPart)) * MULTIPLIER_SELECTED_PAGE)
        val targetPageWith = baseWith * (1 + abs(offsetFractionalPart) * MULTIPLIER_SELECTED_PAGE)

        Log.d(
            "Indicator Solution",
            "currentPage: $currentPage targetPage $targetPage offset ${pagerState.currentPageOffset} offsetIntPart: $offsetIntPart offsetIntPartFractionalPart $offsetFractionalPart"
        )

        repeat(pagerState.pageCount) { index ->
            val width = when (index) {
                currentPage -> currentPageWith
                targetPage -> targetPageWith
                else -> baseWith
            }
            Box(
                modifier = Modifier
                    .width(animateDpAsState(targetValue = width).value)
                    .width(width)
                    .background(indicatorColor)
                    .height(height)
            )
            if (index != pagerState.pageCount - 1) {
                Spacer(modifier = Modifier.width(spacing))
            }
        }
    }
}